package com.xdf.whiteaccount.aop;

import com.xdf.whiteaccount.async.properties.WechatProp;
import com.xdf.whiteaccount.cloudentity.User;
import com.xdf.whiteaccount.cloudentity.UserMill;
import com.xdf.whiteaccount.cloudentity.UserMillView;
import com.xdf.whiteaccount.cloudservice.UserMillViewService;
import com.xdf.whiteaccount.cloudservice.UserService;
import com.xdf.whiteaccount.config.FlywayConfig;
import com.xdf.whiteaccount.config.datasource.DynamicDataSource;
import com.xdf.whiteaccount.config.properties.DbConfig;
import com.xdf.whiteaccount.enums.ResponseEnum;
import com.xdf.whiteaccount.mobileentity.WechatPermission;
import com.xdf.whiteaccount.qrcodeutil.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;

/**
 * @program: white-account
 * @description: 数据获取切面
 * @author: 张柯
 * @create: 2021-06-27 16:42
 **/
@Component
@Slf4j
@Aspect
public class DataGetterControllerAspect extends AbstractAop {
    @Autowired
    private UserService userService;
    @Autowired
    private UserMillViewService userMillViewService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private WechatProp wechatProp;
    @Autowired
    private FlywayConfig flywayConfig;
    @Autowired
    private DbConfig dbConfig;

    @Pointcut("execution(* com.xdf.whiteaccount.mobilecontroller.DataGetterController.*(..))")
    private void cutA() {
    }

    @Pointcut("execution(* com.xdf.whiteaccount.mobilecontroller.WechatPermissionController.*(..))")
    private void cutB() {
    }

    @Pointcut("execution(* com.xdf.whiteaccount.mobilecontroller.WechatPermissionController.modifyMill(..))")
    private void cutModifyMill() {
    }

    /**
     * 动态切换数据源
     *
     * @param proceedingJoinPoint
     * @return
     */
    @Around("cutA()")
    public Object aroundMethodA(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object[] args = proceedingJoinPoint.getArgs();
        Assert.state(ArrayUtils.isNotEmpty(args), "参数不能为空！");
        String openId = String.valueOf(args[0]);
        String key = getDatabaseNameByOpenId(openId);
        if (StringUtils.isEmpty(key)) return null;
        DynamicDataSource dataSource = DynamicDataSource.getInstance();
        if (!dataSource.switchDataSource(key)) {
            dbConfig.setName(key);
            dbConfig.setUrl(dbConfig.getJdbcUrl(key));
            if (dataSource.addAndSwitchDataSource(dbConfig)) {
                //  初始化事件,数据库版本更新
                log.debug("添加{}数据库成功!", key);
                log.warn("开始执行flyway");
                flywayConfig.migrate();
            }
        }
        Object result = proceedingJoinPoint.proceed();
        dataSource.clearDataSource();
        return result;
    }

    /**
     * 微信接口
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("cutB()")
    public Object aroundMethodB(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        DynamicDataSource.getInstance().switchDefault();
        Object[] args = proceedingJoinPoint.getArgs();
        if (ArrayUtils.isNotEmpty(args)) {
            if (args[0] instanceof WechatPermission) {
                WechatPermission record = (WechatPermission) args[0];
                if (record.getWxPlan() == null) record.setWxPlan(false);
                if (record.getWxClientOrder() == null) record.setWxClientOrder(false);
                if (record.getWxDailyYield() == null) record.setWxDailyYield(false);
                if (record.getWxReceivablePayable() == null) record.setWxReceivablePayable(false);
                if (record.getWxFabricStore() == null) record.setWxFabricStore(false);
                if (record.getWxDyePlan() == null) record.setWxDyePlan(false);
                if (record.getWxDyeClientOrder() == null) record.setWxDyeClientOrder(false);
                if (record.getWxWxDyeFabricStore() == null) record.setWxWxDyeFabricStore(false);
                if (record.getWxMaterialStore() == null) record.setWxMaterialStore(false);
                if (record.getWxPermission() == null) record.setWxPermission(false);
                if (record.getPushPlan() == null) record.setPushPlan(false);
                if (record.getPushMaterial() == null) record.setPushMaterial(false);
                if (record.getPushDeliver() == null) record.setPushDeliver(false);
                if (record.getAudit() == null) record.setAudit(false);
            }
        }
        return proceedingJoinPoint.proceed();
    }

    /**
     * 执行修改
     *
     * @param joinPoint
     */
    @Before("cutModifyMill()")
    public void beforeExecuteCutModify(JoinPoint joinPoint) throws Exception {
        Object param = getParam1(joinPoint);
        if (param instanceof UserMill) {
            UserMill record = (UserMill) param;
            Assert.state(StringUtils.isNotEmpty(record.getMillSid()), "客户不能为空！");
            Assert.state(StringUtils.isNotEmpty(record.getOpenId()), "openid不能为空！");
            User user = userService.selectByOpenId(record.getOpenId());
            Assert.notNull(user, ResponseEnum.IS_AUTH.getName());
            Assert.state(user.getCompany() != null && user.getCompany(), ResponseEnum.IS_AUTH.getName());
        }
    }

    /**
     * 抛出异常后操作
     */
    @AfterThrowing("cutA()||cutB()")
    public void throwExc() {
        DynamicDataSource dataSource = DynamicDataSource.getInstance();
        dataSource.clearDataSource();
    }

    /**
     * 根据Code获取openId
     *
     * @param code
     * @param url
     * @param restTemplate
     * @return
     */
    private String getOpenIdByCode(String code, String url, RestTemplate restTemplate) {
        ResponseEntity<Result> result = restTemplate.getForEntity(url + code, Result.class);
        if (HttpStatus.OK == result.getStatusCode()) {
            Result rr = result.getBody();
            return rr.getData();
        }
        return null;
    }

    /**
     * 根据微信code获取数据库名
     *
     * @param code
     * @return
     */
    private String getDatabaseNameByCode(String code) {
        String openId = getOpenIdByCode(code, wechatProp.getOpenidUrl(), restTemplate);
        return getDatabaseNameByOpenId(openId);
    }

    /**
     * 根据openid获取数据库名
     *
     * @param openId
     * @return
     */
    private String getDatabaseNameByOpenId(String openId) {
        log.debug("openId:{}", openId);
        UserMillView record = userMillViewService.selectByOpenId(openId);
        Assert.notNull(record, "该用户无权限查询！");
        Assert.state(record.getBackendName() != null, "该用户无权限查询!");
        log.debug("当前数据库名称：{}", record.getBackendName());
        return record.getBackendName();
    }
}